#include "../include/poller.h"
#include "../include/logger.h"
#include <cassert>
#include <cstdlib>
#include <cstring>

namespace net {

Poller::Poller()
    : _epFd(epoll_create(MAX_EPOLLEVENTS)) 
{  
    if (_epFd < 0)
    {
        // 记录创建失败的致命错误日志
        LOG_FATAL("Thread %d: EPOLL create failed! errno=%d", std::this_thread::get_id(), errno);
        LOG_FLUSH();
    }
    LOG_INFO("Thread %d: Poller created with epfd %d", std::this_thread::get_id(), _epFd);
}

Poller::~Poller()
{
    LOG_INFO("Thread %d: Closing poller with epfd %d", std::this_thread::get_id(), _epFd);
    // 关闭 epoll 实例
    close(_epFd);
}

void Poller::updateEvent(Channel* channel)
{
    bool ret = hasChannel(channel);
    if (ret == false)
    {
        // 若 Channel 不在监控中，则添加到 _channels 中
        _channels.insert(std::make_pair(channel->fd(), channel));
        // 向 epoll 实例注册新的文件描述符
        LOG_INFO("Add channel: %d event: %d", channel->fd(), channel->events());
        return update(channel, EPOLL_CTL_ADD); 
    }
    // 修改已注册的文件描述符的事件设置
    LOG_INFO("Mod channel: %d event: %d", channel->fd(), channel->events());
    return update(channel, EPOLL_CTL_MOD); 
    
}

void Poller::removeEvent(Channel* channel)
{
    LOG_INFO("Remove channel: %d", channel->fd());
    auto it = _channels.find(channel->fd());
    if (it != _channels.end())
    {
        // 从 _channels 中移除该 Channel
        _channels.erase(it);
    }
    // 从 epoll 实例中删除该文件描述符
    update(channel, EPOLL_CTL_DEL); 
}

void Poller::poll(std::vector<Channel*>* active)
{
    LOG_DEBUG("Thread %d: Poll start with epfd %d", std::this_thread::get_id(), _epFd);
    // 调用 epoll_wait 进行阻塞监控
    int nfds = epoll_wait(_epFd, _evs, MAX_EPOLLEVENTS, -1);    // 阻塞等待
    int saveErrno = errno; 
    if (nfds < 0)
    {
        if (saveErrno == EINTR) // 信号打断
        {
            return;
        }
        errno = saveErrno;
        // 记录 epoll_wait 出错的致命错误日志
        LOG_FATAL("Thread %d: Epoll wait error: %s", std::this_thread::get_id(), strerror(errno));
        LOG_FLUSH();
    }

    LOG_DEBUG("%d events happend", nfds);
    
    for (int i = 0; i < nfds; i++) // 添加活跃信息
    {
        auto it = _channels.find(_evs[i].data.fd); 
        // 确保找到对应的 Channel
        assert(it != _channels.end()); 
        // 设置实际就绪的事件
        it->second->setRevents(_evs[i].events); 
        active->push_back(it->second);
    }
}

void Poller::update(Channel* channel, int op)
{
    if (_epFd < 0) 
    {
        LOG_ERROR("Poller::update called with invalid epfd");
        return;
    }
    // 获取 Channel 对应的文件描述符
    int fd = channel->fd();
    struct epoll_event ev;
    ev.data.fd = fd;
    ev.events = channel->events();
    // 调用 epoll_ctl 进行操作
    int ret = epoll_ctl(_epFd, op, fd, &ev);
    if (ret < 0)
    {
        if (op == EPOLL_CTL_DEL)
            // 记录删除操作失败的错误日志
            LOG_ERROR("Thread %d: Epollctl del failed for fd %d", std::this_thread::get_id(), fd);
        else
            // 记录添加或修改操作失败的致命错误日志
            LOG_FATAL("Thread %d: Epollctl add/mod failed for fd %d", std::this_thread::get_id(), fd);
            LOG_FLUSH();
    }
}

bool Poller::hasChannel(Channel* channel)
{
    auto it = _channels.find(channel->fd());
    if (it == _channels.end())
    {
        return false;
    }
    return true;
}

} // namespace net